﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;
using Gpc;
using YArchitech.Revit;
using YJKFloor.Utility;
using YJKRevitCode.RevitTopologySuite.GPCAdapter;
using YJKRGeometry;

namespace ComponentAddRoomInfo.RoomRoofModule
{
	internal class AddDataToEachType
	{
		public AddDataToEachType(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
			this.m_doc = cmdData.Application.ActiveUIDocument.Document;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			filteredElementCollector.OfClass(typeof(SpatialElement)).OfCategory(BuiltInCategory.OST_Rooms);
			FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(this.m_doc);
			ICollection<Element> collection = filteredElementCollector2.OfClass(typeof(Group)).ToElements();
			foreach (Element element in collection)
			{
				Group group = (Group)element;
				if (!this.dicEachGroupToEid.ContainsKey(group))
				{
					this.dicEachGroupToEid.Add(group, new List<ElementId>());
				}
				this.dicEachGroupToEid[group].AddRange(group.GetMemberIds());
			}
			Transaction transaction = new Transaction(this.m_doc, "UnGroups");
			transaction.Start();
			foreach (Element element2 in collection)
			{
				Group group2 = (Group)element2;
				group2.UngroupMembers();
			}
			transaction.Commit();
			foreach (Element element3 in filteredElementCollector)
			{
				Room room = element3 as Room;
				if (room != null)
				{
					LocationPoint locationPoint = room.Location as LocationPoint;
					if (locationPoint != null)
					{
						this.lstRooms.Add(room);
					}
				}
			}
		}

		public int AddDataToWallType()
		{
			new List<Wall>();
			List<int> list = new List<int>();
			Dictionary<ElementId, List<Room>> dictionary = new Dictionary<ElementId, List<Room>>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			IList<Element> list2 = filteredElementCollector.OfClass(typeof(Wall)).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements().ToList<Element>();
			foreach (Element element in list2)
			{
				Wall wall = (Wall)element;
				if (wall.StackedWallOwnerId.IntegerValue == -1)
				{
					int integerValue = wall.Id.IntegerValue;
					for (int i = 0; i < this.lstRooms.Count; i++)
					{
						list = this.GetWallIds(this.lstRooms[i]);
						if (list.Contains(integerValue))
						{
							if (!dictionary.ContainsKey(wall.Id))
							{
								dictionary.Add(wall.Id, new List<Room>());
							}
							dictionary[wall.Id].Add(this.lstRooms[i]);
						}
					}
				}
			}
			return this.GetEachRoomData(dictionary);
		}

		public int AddDataToFloorOrCeilingType(string selectType)
		{
			string g = "6bf57f57-247d-40b9-b9d7-3f9718268890";
			List<Element> list = new List<Element>();
			List<Curve> oneCurves = new List<Curve>();
			List<Curve> otherCurves = new List<Curve>();
			List<Room> list2 = new List<Room>();
			Dictionary<ElementId, List<Room>> dictionary = new Dictionary<ElementId, List<Room>>();
			if (selectType == "FloorType")
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
				IList<Element> collection = filteredElementCollector.OfClass(typeof(Floor)).ToElements().ToList<Element>();
				list.AddRange(collection);
			}
			if (selectType == "CeilingType")
			{
				List<Element> list3 = new List<Element>();
				FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(this.m_doc);
				IList<Element> collection2 = filteredElementCollector2.OfClass(typeof(Floor)).ToElements().ToList<Element>();
				list3.AddRange(collection2);
				FilteredElementCollector filteredElementCollector3 = new FilteredElementCollector(this.m_doc);
				IList<Element> collection3 = filteredElementCollector3.OfClass(typeof(Ceiling)).ToElements().ToList<Element>();
				list.AddRange(collection3);
				Guid guid = new Guid(g);
				foreach (Element element in list3)
				{
					if (Schema.Lookup(guid) != null)
					{
						Entity entity = (element as Floor).FloorType.GetEntity(Schema.Lookup(guid));
						if (entity != null && entity.Schema != null && entity.Schema.SchemaName == "FloorTypeXData")
						{
							list.Add(element);
						}
					}
				}
			}
			FloorEditCommon floorEditCommon = new FloorEditCommon(this.m_Revit);
			Transaction transaction = new Transaction(this.m_doc, "str");
			transaction.Start();
			foreach (Element element2 in list)
			{
				ElementId levelId = element2.LevelId;
				list2 = this.GetRoomsOfCurrentLevel(levelId);
				if (list2.Count != 0)
				{
					oneCurves = UtilityTools.GetDocFloorProfileCvs(element2, floorEditCommon);
					foreach (Room room in list2)
					{
						otherCurves = this.GetRoomCurve(room);
						if (this.JudgePositionRelation(oneCurves, otherCurves))
						{
							if (!dictionary.ContainsKey(element2.Id))
							{
								dictionary.Add(element2.Id, new List<Room>());
							}
							dictionary[element2.Id].Add(room);
						}
					}
				}
			}
			transaction.Commit();
			return this.GetEachRoomData(dictionary);
		}

		public int AddDataToColumnType()
		{
			new List<XYZ>();
			new List<Curve>();
			new List<Curve>();
			new List<FamilyInstance>();
			new List<FamilyInstance>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			filteredElementCollector.OfClass(typeof(Level)).WhereElementIsNotElementType().ToElements();
			Dictionary<ElementId, List<Room>> dictionary = new Dictionary<ElementId, List<Room>>();
			foreach (Room room in this.lstRooms)
			{
				IList<IList<BoundarySegment>> boundarySegments = room.GetBoundarySegments(new SpatialElementBoundaryOptions());
				foreach (IList<BoundarySegment> list in boundarySegments)
				{
					foreach (BoundarySegment segment in list)
					{
						Element element = segment.GetElement(this.m_doc);
						if (element != null && element.Category.Id.IntegerValue == -2000100)
						{
							if (!dictionary.ContainsKey(element.Id))
							{
								dictionary.Add(element.Id, new List<Room>());
							}
							if (!dictionary[element.Id].Contains(room))
							{
								dictionary[element.Id].Add(room);
							}
						}
						else if (element != null && element.Category.Id.IntegerValue == -2001330)
						{
							if (!dictionary.ContainsKey(element.Id))
							{
								dictionary.Add(element.Id, new List<Room>());
							}
							if (!dictionary[element.Id].Contains(room))
							{
								dictionary[element.Id].Add(room);
							}
						}
					}
				}
			}
			return this.GetEachRoomData(dictionary);
		}

		public int AddDataToWallDecorateType()
		{
			List<ElementId> list = new List<ElementId>();
			List<int> list2 = new List<int>();
			new List<WallSweep>();
			Dictionary<ElementId, List<Room>> dictionary = new Dictionary<ElementId, List<Room>>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			IList<Element> list3 = filteredElementCollector.OfClass(typeof(WallSweep)).ToElements().ToList<Element>();
			foreach (Element element in list3)
			{
				WallSweep wallSweep = (WallSweep)element;
				list = wallSweep.GetHostIds().ToList<ElementId>();
				foreach (ElementId elementId in list)
				{
					foreach (Room room in this.lstRooms)
					{
						list2 = this.GetWallIds(room);
						if (list2.Contains(elementId.IntegerValue))
						{
							if (!dictionary.ContainsKey(wallSweep.Id))
							{
								dictionary.Add(wallSweep.Id, new List<Room>());
							}
							dictionary[wallSweep.Id].Add(room);
						}
					}
				}
			}
			return this.GetEachRoomData(dictionary);
		}

		public int AddDataToOtherType()
		{
			new List<FamilyInstance>();
			List<Element> list = new List<Element>();
			Dictionary<ElementId, List<Room>> dictionary = new Dictionary<ElementId, List<Room>>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			ICollection<Element> collection = filteredElementCollector.OfClass(typeof(FamilyInstance)).ToElements();
			foreach (Element item in collection)
			{
				list.Add(item);
			}
			for (int i = 0; i < list.Count; i++)
			{
				int integerValue = list[i].Category.Id.IntegerValue;
				if (integerValue == -2000100 || integerValue == -2001330)
				{
					list.Remove(list[i]);
					i--;
				}
			}
			foreach (Element element in list)
			{
				FamilyInstance familyInstance = (FamilyInstance)element;
				Room room = null;
				try
				{
					if (familyInstance.Room != null)
					{
						room = familyInstance.Room;
					}
					else if (familyInstance.FromRoom != null)
					{
						room = familyInstance.FromRoom;
					}
					else if (familyInstance.ToRoom != null)
					{
						room = familyInstance.ToRoom;
					}
					if (room != null)
					{
						if (!dictionary.ContainsKey(familyInstance.Id))
						{
							dictionary.Add(familyInstance.Id, new List<Room>());
						}
						dictionary[familyInstance.Id].Add(room);
					}
				}
				catch (Exception)
				{
				}
			}
			return this.GetEachRoomData(dictionary);
		}

		private int GetEachRoomData(Dictionary<ElementId, List<Room>> dicEachWallToRoom)
		{
			int num = 0;
			Element instance = null;
			Transaction transaction = new Transaction(this.m_doc, "AddRoomDataToComponent");
			transaction.Start();
			foreach (KeyValuePair<ElementId, List<Room>> keyValuePair in dicEachWallToRoom)
			{
				instance = this.m_doc.GetElement(keyValuePair.Key);
				num++;
				string text = null;
				string text2 = null;
				foreach (Room room in keyValuePair.Value)
				{
					try
					{
						if (room != null)
						{
							if (keyValuePair.Value.Count == 1)
							{
								text += room.GetParameter("名称").AsString();
								text2 += this.GetRoomNum(room);
							}
							else
							{
								text = text + room.GetParameter("名称").AsString() + ",";
								text2 = text2 + this.GetRoomNum(room) + ",";
							}
						}
					}
					catch
					{
					}
				}
				if (text != null || text2 != null)
				{
					this.AddSharedParaToInstance(instance, text, text2);
				}
			}
			transaction.Commit();
			return num;
		}

		private string GetRoomNum(Room inputRoom)
		{
			foreach (object obj in inputRoom.Parameters)
			{
				Parameter parameter = (Parameter)obj;
				if (parameter != null)
				{
					string name = parameter.Definition.Name;
					if (name == "房间编号")
					{
						IList<Parameter> parameters = inputRoom.GetParameters("房间编号");
						if (parameters.Count != 0)
						{
							string text = parameters[0].AsInteger().ToString();
							if (text != null)
							{
								return text;
							}
						}
					}
				}
			}
			return inputRoom.Number;
		}

		private void AddSharedParaToInstance(Element instance, string roomName, string roomNum)
		{
            BuiltInCategory integerValue = (BuiltInCategory)instance.Category.Id.IntegerValue;
			Dictionary<string, ParameterType> dictionary = new Dictionary<string, ParameterType>();
			if (instance.GetParameter("房间名称") == null)
			{
                dictionary.Add("房间名称", (ParameterType)1);
			}
			if (instance.GetParameter("房间编号") == null)
			{
                dictionary.Add("房间编号", (ParameterType)1);
			}
			if (dictionary.Count > 0)
			{
				SharedParameter.InsertSharedParameter(this.m_doc, integerValue, "附着房间信息", dictionary, true, true);
			}
			instance.GetParameter("房间名称").Set(roomName);
			instance.GetParameter("房间编号").Set(roomNum);
			this.m_doc.Regenerate();
		}

		private List<int> GetWallIds(Room room)
		{
			List<int> list = new List<int>();
			IList<IList<BoundarySegment>> boundarySegments = room.GetBoundarySegments(new SpatialElementBoundaryOptions());
			foreach (IList<BoundarySegment> list2 in boundarySegments)
			{
				foreach (BoundarySegment segment in list2)
				{
					Wall wall = segment.GetElement(this.m_doc) as Wall;
					if (wall != null && !list.Contains(wall.Id.IntegerValue))
					{
						list.Add(wall.Id.IntegerValue);
					}
				}
			}
			return list;
		}

		private List<Curve> GetRoomCurve(Room room)
		{
			List<Curve> list = new List<Curve>();
			IList<IList<BoundarySegment>> boundarySegments = room.GetBoundarySegments(new SpatialElementBoundaryOptions());
			foreach (IList<BoundarySegment> list2 in boundarySegments)
			{
				foreach (BoundarySegment segment in list2)
				{
					Curve curve = segment.GetCurve();
					if (null != curve)
					{
						list.Add(curve);
					}
				}
			}
			return list;
		}

		private List<Room> GetRoomsOfCurrentLevel(ElementId inputId)
		{
			List<Room> list = new List<Room>();
			foreach (Room room in this.lstRooms)
			{
				if (room.LevelId == inputId)
				{
					list.Add(room);
				}
			}
			return list;
		}

		private bool JudgePositionRelation(List<Curve> oneCurves, List<Curve> otherCurves)
		{
			try
			{
				Polygon polygon = this.ConstructPolygon(oneCurves);
				Polygon polygon2 = this.ConstructPolygon(otherCurves);
				IPolygon polygon3 = polygon.ClipPolygon(polygon2, ClipOp.Int);
				GraphicsPath graphicsPath = polygon3.ToGraphicsPath(ContourType.All, GraphicsPathType.Lines);
				IPolygon polygon4 = polygon.ClipPolygon(polygon2, ClipOp.Xor);
				GraphicsPath graphicsPath2 = polygon4.ToGraphicsPath(ContourType.All, GraphicsPathType.Lines);
				IPolygon polygon5 = polygon.ClipPolygon(polygon2, ClipOp.Diff);
				GraphicsPath graphicsPath3 = polygon5.ToGraphicsPath(ContourType.All, GraphicsPathType.Lines);
				IPolygon polygon6 = polygon2.ClipPolygon(polygon, ClipOp.Diff);
				GraphicsPath graphicsPath4 = polygon6.ToGraphicsPath(ContourType.All, GraphicsPathType.Lines);
				double value = 1.0;
				double value2 = 1.0;
				try
				{
					value = this.CalculateArea(graphicsPath3.PathPoints);
					value2 = this.CalculateArea(graphicsPath4.PathPoints);
				}
				catch (Exception)
				{
				}
				string a = null;
				if (graphicsPath.PointCount < 1)
				{
					a = "Separation";
				}
				else if (graphicsPath2.PointCount < 1)
				{
					a = "Equal";
				}
				else if (graphicsPath3.PointCount > 1 && (graphicsPath4.PointCount < 1 || Math.Abs(value2) < 1.0))
				{
					a = "SuperSet";
				}
				else if (graphicsPath4.PointCount > 1 && (graphicsPath3.PointCount < 1 || Math.Abs(value) < 1.0))
				{
					a = "SubSet";
				}
				else if (graphicsPath3.PointCount > 1 && graphicsPath4.PointCount > 1)
				{
					a = "Intersection";
				}
				if (a == "Equal" || a == "SuperSet" || a == "SubSet" || a == "Intersection")
				{
					return true;
				}
			}
			catch (Exception)
			{
			}
			return false;
		}

		private Polygon ConstructPolygon(List<Curve> lstinputCurves)
		{
			return GpcPolygonController.ConstructPolygon(lstinputCurves, null);
		}

		private double CalculateArea(PointF[] points)
		{
			List<double> list = new List<double>();
			List<double> list2 = new List<double>();
			foreach (PointF pointF in points)
			{
				list.Add((double)pointF.X);
				list2.Add((double)pointF.Y);
			}
			return Geometry.AoArea(list.Count, list.ToArray(), list2.ToArray());
		}

		private List<XYZ> BreakColumnByLevel(List<Element> levels, Element column)
		{
			List<XYZ> list = new List<XYZ>();
			XYZ point = ((column as FamilyInstance).Location as LocationPoint).Point;
			list.Add(point);
			Level level = null;
			Level level2 = null;
			try
			{
				ElementId elementId = column.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).AsElementId();
				ElementId elementId2 = column.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).AsElementId();
				level = (this.m_doc.GetElement(elementId) as Level);
				level2 = (this.m_doc.GetElement(elementId2) as Level);
			}
			catch
			{
				return null;
			}
			double num = column.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).AsDouble();
			double num2 = column.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).AsDouble();
			double value = level.Elevation + num;
			double value2 = level2.Elevation + num2;
			List<Level> list2 = new List<Level>();
			foreach (Element element in levels)
			{
				Level level3 = (Level)element;
				if (Math.Round(value, 2) < Math.Round(level3.Elevation, 2) && Math.Round(level3.Elevation, 2) < Math.Round(value2, 2))
				{
					list2.Add(level3);
				}
			}
			foreach (Level level4 in list2)
			{
				list.Add(new XYZ(point.X, point.Y, level4.Elevation));
			}
			return list;
		}

		private Document m_doc;

		private ExternalCommandData m_Revit;

		public Dictionary<Group, List<ElementId>> dicEachGroupToEid = new Dictionary<Group, List<ElementId>>();

		private List<Room> lstRooms = new List<Room>();
	}
}
